package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.json.JSONUtil;
import com.zzyl.dto.LoginDto;
import com.zzyl.entity.User;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.properties.JwtProperties;
import com.zzyl.service.LoginService;
import com.zzyl.service.UserService;
import com.zzyl.utils.JwtUtil;
import com.zzyl.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @className: LoginServiceImpl
 * @description:
 * @author: InnovatorX
 * @date: 2024/6/5 20:02
 * @Version: 1.0
 */
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {
    @Autowired
    private UserService userService;
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private ResourceServiceImpl resourceService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public UserVo login(LoginDto dto) {
        // 用户名密码登录
        // 根据用户名查询用户
        User user = userService.findByUsername(dto.getUsername());
        //检验用户是否存在
        if (user == null) {
            log.error("用户不存在");
            throw new BaseException(BasicEnum.USER_EMPTY_EXCEPTION);
        }
        //检验用户是否被禁用
        if ("1".equals(user.getDataState())) {
            log.error("用户被禁用");
            throw new BaseException(BasicEnum.USER_DISABLE_EXCEPTION);
        }
        //检验密码是否正确, BCrypt加密
        boolean checkpw = BCrypt.checkpw(dto.getPassword(), user.getPassword());
        if (!checkpw) {
            log.error("密码错误");
            throw new BaseException(BasicEnum.ORIGINAL_PASSWORD_ERROR);
        }
        // 生成的对象是User, 返回的对象是UserVo, 需要进行对象的转换
        UserVo userVo = BeanUtil.toBean(user, UserVo.class);
        // 密码脱敏
        userVo.setPassword("");
        // 根据用户名生成jwt
        Map<String, Object> claims = new HashMap<>();
        // 放入token的用户数据
        claims.put("currentUser", JSONUtil.toJsonStr(userVo));
        /**
         * 创建JSON Web Token (JWT)
         *
         * 使用JWTUtil类提供的静态方法createJWT来构建JWT。此方法封装了JWT的创建过程，包括设置秘钥、过期时间和声明。
         *
         * @param base64EncodedSecretKey 经过Base64编码的秘钥，用于签名JWT，确保JWT的完整性。
         * @param ttl JWT的过期时间，指定JWT的有效期。
         * @param claims JWT的声明，包含在JWT中需要传递的信息。
         * @return 生成的JWT字符串。
         */
        String token = JwtUtil.createJWT(jwtProperties.getBase64EncodedSecretKey(), jwtProperties.getTtl(), claims);

        // 把jwt放入到userVo中
        userVo.setUserToken(token);

        // 查询用户可以操作的按钮资源信息
        Long userVoId = userVo.getId();
        // 查询用户可以操作的按钮资源信息
        List<String> urls = resourceService.findButtonResourceByUserId(userVoId);
        // 放入redis 使用String key: userId  value:urls
        redisTemplate.opsForValue().set("user:access:url" + userVoId, JSONUtil.toJsonStr(urls));

        // 返回Token
        return userVo;
    }
}
